#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <unistd.h>
#include "thread.hpp"
#include "lockGurad.hpp"
#include "log.hpp"
const int g_thread_num = 3;

template<class T>
class ThreadPool
{
private:
     ThreadPool(int thread_num = g_thread_num)
        :num_(thread_num)
    {
        pthread_mutex_init(&lock,nullptr);
        pthread_cond_init(&cond,nullptr);
        for(int i = 1; i <= num_; i++)
        {
            threads_.push_back(new Thread(i,routine,this));
        }
    }

    ThreadPool(const ThreadPool<T>& tp) = delete;
    const ThreadPool<T>& operator=(const ThreadPool<T>& tp) = delete;
public:
    pthread_mutex_t* getMutexs()
    {
        return &lock;
    }

    bool IsEmpty()
    {
        return task_queue_.empty();
    }

    void waitCond()
    {
        pthread_cond_wait(&cond,&lock);
    }

    T getTask()
    {
        T t = task_queue_.front();
        task_queue_.pop();
        return t;
    }
public:
    // 考虑一下多线程使用单例的过程
    static ThreadPool<T>* getThreadPool(int num = g_thread_num)
    {
         // 可以有效减少未来必定要进行加锁检测的问题
        // 拦截大量的在已经创建好单例的时候，剩余线程请求单例的而直接访问锁的行为
        if(nullptr == thread_ptr)
        {
            lockGuard lock(&mutex);
            // 但是，未来任何一个线程想获取单例，都必须调用getThreadPool接口
            // 但是，一定会存在大量的申请和释放锁的行为，这个是无用且浪费资源的
            if(nullptr == thread_ptr)
            {
                thread_ptr = new ThreadPool<T>(num);
            }
        }
        return thread_ptr;
    }
    //线程池本质也是一个生产消费模型
    //成员函数还有this指针，要弄成静态
    static void* routine(void* args)//消费任务
    {
        ThreadData* td = (ThreadData*)args;
        ThreadPool<T>* tp = (ThreadPool<T>*)td->args_;//注意取的是td的args_

        while(true)
        {
            T task;
            {
                lockGuard lockguard(tp->getMutexs());
                while(tp->IsEmpty()) tp->waitCond();//等待可能失败，需要while循环
                //读取任务
                task = tp->getTask();// 任务队列是共享的-> 将任务从共享，拿到自己的私有空间
            }
            task(td->name_);
        }
    }   


    void run()
    {
        for(auto& iter : threads_)
        {
            iter->start();
            // std::cout << iter->name() << " 启动成功 " << std::endl;
            logMessage(NORMAL,"%s%s",iter->name().c_str(), "启动成功");
        }
    }

    // void join()
    // {
    //     for(auto& iter : threads_)
    //     {
    //         iter->join();
    //     }
    // }
    void pushTask(const T& task)//生产任务
    {
        lockGuard lockguard(&lock);//加锁
        task_queue_.push(task);
        pthread_cond_signal(&cond);//唤醒
    }

    ~ThreadPool()
    {
        for(auto& iter : threads_)
        {
            iter->join();
            delete iter;
        }
        pthread_mutex_destroy(&lock);
        pthread_cond_destroy(&cond);
    }

private:
    std::vector<Thread*> threads_;
    int num_;//创建线程池个数
    std::queue<T>task_queue_;//任务队列
    pthread_mutex_t lock;//锁
    pthread_cond_t cond;//条件变量
    static ThreadPool<T>* thread_ptr;
    static pthread_mutex_t mutex;
};

template<typename T>
ThreadPool<T>* ThreadPool<T>::thread_ptr = nullptr;

template<typename T>
pthread_mutex_t ThreadPool<T>::mutex = PTHREAD_MUTEX_INITIALIZER;